package com.motui;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;

import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
import java.util.logging.Logger;

/**
 * Dubbo 本地调试代理
 *
 * @author motui
 * @date 2018/9/19 14:21
 */
public class DubboLocalDebugAgent implements ClassFileTransformer {

    private static Logger logger = Logger.getLogger("com.motui.DubboLocalDebugAgent");

    /**
     * AbstractLoadBalance类名称
     */
    private static final String CLASS_NAME = "com.alibaba.dubbo.rpc.cluster.loadbalance.AbstractLoadBalance";


    @Override
    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
        className = className.replace("/", ".");
        if (className.equals(CLASS_NAME)) {
            logger.info("调用目标类[" + CLASS_NAME + "]");
            ClassPool pool = ClassPool.getDefault();
            try {
                CtClass abstractLoadBalance = pool.get(className);
                //select 方法
                CtMethod select = abstractLoadBalance.getDeclaredMethod("select");
                /*
                  插入代码
                  1、获取本机的IP
                  2、遍历所有的提供者，获取提供者的URL，判断是否包含本机提供者
                    如果包含，则返回本机的提供者
                    如果不包含，则跳过，按照默认设置选择提供者
                 */
                String sb = "String localHost = com.alibaba.dubbo.common.utils.NetUtils.getLocalHost();\n" +
//                        "    System.out.println(\"=========> 本机Ip: \" + localHost);\n" +
                        "    for (int i = 0; i < $1.size(); i++) {\n" +
                        "        com.alibaba.dubbo.common.Node node = (com.alibaba.dubbo.common.Node) $1.get(i);\n" +
                        "        com.alibaba.dubbo.common.URL nodeUrl = (com.alibaba.dubbo.common.URL) node.getUrl();\n" +
                        "        String s = nodeUrl.toFullString();\n" +
//                        "        System.out.println(\"=========> invoker -> url: \" + s);\n" +
                        "        if (s.contains(\"dubbo://\" + localHost)) {\n" +
//                        "             System.out.println(\"=========> 本机提供的服务,返回本机提供的invoker······\");\n" +
                        "             return $1.get(i);\n" +
                        "        } else {\n" +
//                        "             System.out.println(\"=========> 不是本机提供的服务,跳过·····\");\n" +
                        "        }\n" +
                        "     }" +
                        "     System.out.println(\"=========> 本机没有提供的服务,按照默认设置选择服务·····\");\n";
                select.insertAfter(sb);

                return abstractLoadBalance.toBytecode();
            } catch (Exception e) {
                logger.severe("dubbo local debug 异常 ：" + e.getMessage());
            }
        }
        return null;
    }
}
